package jwtx

import (
	"fmt"
	"net/http"
	"time"

	"gitee.com/workits/pkgs/cachex"
	"github.com/golang-jwt/jwt"
	"github.com/golang-jwt/jwt/request"
	jsoniter "github.com/json-iterator/go"
)

// Gen 生成JWT token、失效时间
func Gen(cfg Config, claims DefinedClaims, uInfo any) (string, time.Time, error) {
	// 生成JWT token
	issuedAt := time.Now()
	expiresAt := issuedAt.Add(time.Duration(cfg.Expired) * time.Second)
	claims.StandardClaims = jwt.StandardClaims{
		ExpiresAt: expiresAt.Unix(),
		IssuedAt:  issuedAt.Unix(),
	}
	tok := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	token, err := tok.SignedString([]byte(cfg.Secret))
	if err != nil {
		return token, expiresAt, err
	}

	// 将用户信息存入缓存
	json := jsoniter.ConfigCompatibleWithStandardLibrary
	uBytes, err := json.Marshal(uInfo)
	if err != nil {
		return token, expiresAt, err
	}
	err = cachex.C.Set(fmt.Sprintf(CacheKey, claims.UID), string(uBytes), time.Duration(cfg.Expired)*time.Second)

	return token, expiresAt, err
}

// VerifyRequest 验证
func VerifyRequest(cfg Config, req *http.Request) (string, error) {
	// 解析token
	// 从header中获取: Authorization（优先）, token格式兼容Bearer头部
	// 从path中获取：access_token
	var claims DefinedClaims
	if _, err := request.ParseFromRequest(req, request.OAuth2Extractor, func(token *jwt.Token) (any, error) {
		return []byte(cfg.Secret), nil
	}, request.WithClaims(&claims)); err != nil {
		return "", err
	}

	// 从缓存中查询用户信息
	ustring, err := cachex.C.Get(fmt.Sprintf(CacheKey, claims.UID))
	if err != nil {
		return "", err
	}
	if len(ustring) == 0 {
		return "", fmt.Errorf("缓存中不存在该用户: %v", claims.UID)
	}

	return ustring, nil
}
